﻿using System;
using System.IO;
using System.IO.Compression;

namespace NET.HLW5a.Snippets.Streams
{
    /// <summary>
    /// Example for compressing and decompressing a stream
    /// </summary>
    public static class GZip
    {
        /// <summary>
        /// Returns compressed source stream in a new <see cref="System.IO.Stream"/>
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static Stream Compress(Stream src)
        {
            Stream dst = new MemoryStream(); // create destination stream to hold the compressed data
            using (GZipStream comp = new GZipStream(dst, CompressionMode.Compress, true)) // leaveOpen = true; compressed destination stream is not disposed
            {
                src.Seek(0L, SeekOrigin.Begin); // rewind uncompressed source stream
                for (Int32 b = src.ReadByte(); b != -1; b = src.ReadByte()) comp.WriteByte((Byte)b); // copy source stream onto destination stream while compressing
                comp.Close(); // close compression stream so that it writes out all cached data; destination stream is not disposed (see above)
                dst.Seek(0L, SeekOrigin.Begin); // rewind compressed destination stream
            }
            return dst; // return compressed destination stream
        }

        /// <summary>
        /// Returns decompressed source stream in a new <see cref="System.IO.Stream"/>
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        public static Stream Decompress(Stream src)
        {
            Stream dst = new MemoryStream(); // create destination stream to hold the decompressed data
            using (GZipStream decomp = new GZipStream(src, CompressionMode.Decompress)) // leaveOpen = false; compressed source stream is disposed
            {
                src.Seek(0L, SeekOrigin.Begin); // rewind compressed source stream
                for (Int32 b = decomp.ReadByte(); b != -1; b = decomp.ReadByte()) dst.WriteByte((Byte)b); // copy source stream onto destination stream while decompressing
                //decomp.Close(); // close compression stream so that it writes out all cached data; destination stream is not disposed (see above)
                dst.Seek(0L, SeekOrigin.Begin); // rewind uncompressed destination stream
            }
            return dst; // return uncompressed destination stream
        }
    }
}
